﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class HeroCardPanel : MonoBehaviour
{
    [SerializeField]public GameObject _cardPrefab;
    Transform _anchor;
    private LinkedList<HeroCardData> _heros = new LinkedList<HeroCardData>();
    [SerializeField] float _maxY;
    [SerializeField] float _minY;
    [SerializeField] float _maxX;
    [SerializeField] float _minX;
    [SerializeField] float _maxAng  = 30;
    [SerializeField] float _maxCount = 7;
    public int num;
    void Start()
    {
        _anchor = transform;
        for (int i = 0;i< num; i++)
        {
            _heros.AddLast(new HeroCardData() { lv = i});
        }
        new TaskManage.Task(InitCards(_heros));
    }

    void Update() {
        if (Input.GetKeyDown(KeyCode.Q)) {
           // AddCard();
        }
        if (Input.GetKeyDown(KeyCode.W)) {
            //LoseCard();
        }
    }

    public IEnumerator InitCards(LinkedList<HeroCardData> contextData)
    {
        yield return 0;
        float t = 0.35f/_maxCount;
        LinkedListNode<HeroCardData> curr = contextData.First;
        while(true)
        {
            AddHero(curr.Value);
            if (curr.Next == null)
                break;
            curr = curr.Next;
            yield return new WaitForSeconds(t);
        }
    }
    Vector3 CardCreatePosition()
    {
        return new Vector3(_minX + 512,0,0);
    }
    float Index2Y(int idx)
    {
        int count = _anchor.childCount-1;
        if (count < 1)
            return 0;
        float half =  count * 0.5f ;
        float halfMax = (_maxCount -1) * 0.5f;
        float distance = idx - half;
        if (distance > 0)
        {
            return Mathf.Lerp(0, _minY , distance / halfMax);
        }
        return Mathf.Lerp(0, _maxY , -distance / halfMax);
    }
    public float GetX(float y)
    {
        if (y > 0)
        {
            if (y > _maxY)
                return _maxX + (y - _maxY)*0.6f;
            return Mathf.Lerp(_minX, _maxX, y / _maxY);
        }
        else
        {
            if (y <_minY)
                return _maxX + (_minY - y)*0.6f;
            return Mathf.Lerp(_minX, _maxX, y / _minY);
        }
    }

    public float GetAngle(float y)
    {
        if (y > 0)
            return Mathf.Lerp(0, -_maxAng+3, y / _maxY);
        else
            return Mathf.Lerp(0, _maxAng+3, y / _minY);
    }


    public void AddHero(HeroCardData hero ) {
        if(_anchor.childCount < _maxCount)
        {
            GameObject go = GameObject.Instantiate(_cardPrefab,_anchor);
            go.transform.localPosition = CardCreatePosition();
            go.transform.localEulerAngles = Vector3.zero;
            HeroCard card = go.GetComponent<HeroCard>();
            card.SetPanel(this);
            float y = Index2Y(card.transform.GetSiblingIndex());
            card.OnAnimateMoveTo(new Vector3(GetX(y),y,0),_maxAng);
            card.SetViewData(hero);
            OnAddHeroCard(card);

        }
    }
    public void OnAddHeroCard(HeroCard card)
    {
        Transform carTran = card.transform;
        for(int i = 0;i< _anchor.childCount;i++)
        {
            Transform t = _anchor.GetChild(i);
            if(t != carTran)
            {
                float y = Index2Y(i);
                float x = GetX(y);
                float a = GetAngle(y);
                t.GetComponent<HeroCard>().OnAnimateMoveTo(new Vector3(x,y,0),a);
            }
        }
    }
    public void RemoveHero(HeroCardData hero) {

    }
    public void OnRemoveHeroCard(HeroCard card)
    {
        Transform carTran = card.transform;
        for (int i = 0; i < _anchor.childCount; i++)
        {
            Transform t = _anchor.GetChild(i);
            if (t != carTran)
            {
                float y = Index2Y(i);
                float x = GetX(y);
                float a = GetAngle(y);
                t.GetComponent<HeroCard>().OnAnimateMoveTo(new Vector3(x, y, 0), a);
            }
        }
    }

    public void OnDragCard(PointerEventData eventData, HeroCard card)
    {
        if (iconObj)
        {
            FollawMouse(eventData);
            return;
        }
        Vector3 pos = eventData.position - eventData.pressPosition;
        //create icon
        if (pos.x < -200)
        {
            CreateDragIcon(card);
            FollawMouse(eventData);
            SetInVisable(card);
            this.OnRemoveHeroCard(card);
            return;
        }
        //update position
        Vector3 to = card.PointerDownTranPos + pos;
        float x = this.GetX(to.y);
        if (to.x > x)
            to.x = x;
        Transform cardTran = card.transform;
        cardTran.localPosition = to;
        cardTran.localEulerAngles = new Vector3(0, 0, this.GetAngle(to.y));
        //更新其他
        Vector2 delta = eventData.delta;
        float dy = delta.y;
        float boundUp = _maxY + 100,boundDown = _minY -100;
        int heroNum = _heros.Count;
        //用于循环
        Transform first = null, end = null;
        int lastIndx = _anchor.childCount - 1;
        bool isInsertFirst =false, isAppendEnd = false;
        for (int i = 0; i < _anchor.childCount; i++)
        {
            Transform t = _anchor.GetChild(i);
            if (i == 0)
                first = t;
            if (i == lastIndx)
                end = t;
            if(t != cardTran)
            {
                float y1 = t.localPosition.y + dy;
                if(heroNum > 5)
                {
                    if (delta.y > 0 && y1 > boundUp)
                    {
                        isAppendEnd = true;
                        continue;
                    }
                    if (delta.y < 0 && y1 < boundDown)
                    {
                        isInsertFirst = true;
                        continue;
                    }
                }
                float x1 = GetX(y1);
                t.localPosition = new Vector3(x1,y1,0);
                t.localEulerAngles = new Vector3(0,0,GetAngle(y1));
            }
        }
        if (isAppendEnd)
        {
            OnAppendEnd(first , end);
        }
        if (isInsertFirst)
        {
            OnInsertFirst(end , first);
        }
    }

    int IndexBeforInVisable;
    public void OnDragCardEnd(PointerEventData data, HeroCard card)
    {
        if (iconObj)
        {
            Vector3 v = iconObj.transform.localPosition;
            Destroy(iconObj);
            SetVisable(card);
            card.transform.localPosition = v;
            v.y = this.Index2Y(IndexBeforInVisable);
            v.x = GetX(v.y);
            float ang = this.GetAngle(v.y);
            card.OnAnimateMoveTo(v, ang);
            this.OnAddHeroCard(card);
        }
        else
        {
            Vector3 v = new Vector3();
            v.y = Index2Y(card.transform.GetSiblingIndex());
            v.x = GetX(v.y);
            float ang = this.GetAngle(v.y);
            card.OnAnimateMoveTo(v, ang);
            OnAddHeroCard(card);
        }
    }
    void OnAppendEnd(Transform first,Transform last)
    {
        float y1 = Index2Y(0);
        float y2 = Index2Y(1);
        float y = last.localPosition.y - Mathf.Abs(y1 - y2);
        float x = GetX(y);
        float ang = GetAngle(y);
        first.transform.SetAsLastSibling();
        first.transform.localPosition = new Vector3(x,y);// CardCreatePosition();
        first.transform.localEulerAngles = new Vector3(0, 0, ang);
        HeroCard heroCard = first.GetComponent<HeroCard>();
        //heroCard.OnAnimateMoveTo(new Vector3(x, y), ang);
        //数据
        HeroCardData prev = last.GetComponent<HeroCard>().HeroData;
        LinkedListNode<HeroCardData> node = _heros.Find(prev);
        if(node == _heros.Last)
        {
            heroCard.SetViewData(_heros.First.Value);
        }
        else
        {
            heroCard.SetViewData(node.Next.Value);
        }
    }
    void OnInsertFirst(Transform last,Transform first)
    {
        float y1 = Index2Y(_anchor.childCount - 1);
        float y2 = Index2Y(_anchor.childCount - 2);
        float y = first.localPosition.y + Mathf.Abs(y1 - y2);
        float x = GetX(y);
        float ang = GetAngle(y);
        last.transform.SetAsFirstSibling();
        last.transform.localPosition = new Vector3(x,y);// CardCreatePosition();
        last.transform.localEulerAngles = new Vector3(0, 0, ang);
        HeroCard heroCard = first.GetComponent<HeroCard>();
        //heroCard.OnAnimateMoveTo(new Vector3(x, y), ang);
        //数据
        HeroCardData prev = first.GetComponent<HeroCard>().HeroData;
        LinkedListNode<HeroCardData> node = _heros.Find(prev);
        if (node == _heros.First)
        {
            heroCard.SetViewData(_heros.Last.Value);
        }
        else
        {
            heroCard.SetViewData(node.Previous.Value);
        }
    }
    void SetInVisable(HeroCard card)
    {
        IndexBeforInVisable = card.transform.GetSiblingIndex();
        card.transform.SetParent(transform.parent);
        foreach (var v in card.GetComponentsInChildren<Graphic>())
            v.enabled = false;
    }

    void SetVisable(HeroCard card)
    {
        card.transform.SetParent(_anchor);
        card.transform.SetSiblingIndex(IndexBeforInVisable);
        foreach (var v in card.GetComponentsInChildren<Graphic>())
            v.enabled = true;
    }
    GameObject iconObj;
    void CreateDragIcon(HeroCard card)
    {
       Canvas _canvas = GetComponentInParent<Canvas>();
        iconObj = new GameObject("_icon");
        iconObj.transform.SetParent(_canvas.transform);
        Image img = iconObj.AddComponent<Image>();
        img.sprite = card.GetComponent<Image>().sprite;

        iconObj.transform.localScale = Vector3.one;
        RectTransform rect = iconObj.GetComponent<RectTransform>();
        rect.sizeDelta = new Vector2(150, 150);
    }
    void FollawMouse(PointerEventData eventData)
    {
        Vector2 result;
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            transform.parent as RectTransform,
            eventData.position,
            eventData.pressEventCamera,
            out result))
        {
            iconObj.transform.localPosition = result;
        }
    }

}
